Skip to content

Conversation

@danielroe
Copy link
Member

πŸ”— Linked issue

❓ Type of change

  • 🐞 Bug fix (a non-breaking change that fixes an issue)
  • ⚠️ Breaking change (fix or feature that would cause existing functionality to change)

πŸ“š Description

this updates us to h3 v2, which is needed for nitro v3. I'm going to see if it's possible to make this a non-breaking change (ie support both h3 v2 and v1) but for now this PR can be used in nuxt/nuxt#33005.

@danielroe danielroe self-assigned this Dec 15, 2025
@pkg-pr-new
Copy link

pkg-pr-new bot commented Dec 15, 2025

Open in StackBlitz

npm i https://pkg.pr.new/@nuxt/test-utils@1515

commit: 4f3dfec

@danielroe danielroe changed the title feat(runtime-utils)!: update to h3 v2 feat(runtime-utils): support h3 v2 Jan 5, 2026
@danielroe danielroe marked this pull request as ready for review January 5, 2026 14:26
@danielroe danielroe merged commit 9719a5b into main Jan 5, 2026
7 checks passed
@danielroe danielroe deleted the feat/nitro-v3 branch January 5, 2026 14:27
@github-actions github-actions bot mentioned this pull request Jan 5, 2026
@Youhan
Copy link

Youhan commented Jan 7, 2026

@danielroe Would this possibly cause issue with pnpm when using another module like nuxt-site-config which has "h3": ">=1" as peerDependencies?

  • with v3.21.0, pnpm resolves all peer dependencies of h3 as 1.15.4
  • with v3.23.0, pnpm resolves some h3 as 1.15.4 and some as 2.0.1-rc.7
  • and looks like nuxt-site-config is not ready for h3 v2, cause nitro server crashes.
with v3.21.0 I get this
❯ pnpm why h3
Legend: production dependency, optional only, dev only

devDependencies:
@nuxt/eslint 1.12.1
└─┬ @eslint/config-inspector 1.4.2
  └── h3 1.15.4
@nuxt/fonts 0.12.1
β”œβ”€β”¬ fontless 0.1.0
β”‚ └─┬ unstorage 1.17.3
β”‚   └── h3 1.15.4
β”œβ”€β”€ h3 1.15.4
└─┬ unstorage 1.17.3
  └── h3 1.15.4
@nuxt/image 2.0.0
β”œβ”€β”€ h3 1.15.4
└─┬ ipx 3.1.1
  β”œβ”€β”€ h3 1.15.4
  β”œβ”€β”¬ listhen 1.9.0
  β”‚ └── h3 1.15.4
  └─┬ unstorage 1.17.3
    └── h3 1.15.4
@nuxt/scripts 0.13.2
β”œβ”€β”€ h3 1.15.4
└─┬ unstorage 1.17.3
  └── h3 1.15.4
@nuxt/test-utils 3.21.0
└── h3 1.15.4
@nuxt/ui 4.3.0
└─┬ @nuxt/fonts 0.12.1
  β”œβ”€β”¬ fontless 0.1.0
  β”‚ └─┬ unstorage 1.17.3
  β”‚   └── h3 1.15.4
  β”œβ”€β”€ h3 1.15.4
  └─┬ unstorage 1.17.3
    └── h3 1.15.4
@nuxthub/core 0.9.1
β”œβ”€β”€ h3 1.15.4
└─┬ unstorage 1.17.3
  └── h3 1.15.4
@nuxtjs/seo 3.3.0
β”œβ”€β”¬ @nuxtjs/robots 5.6.7
β”‚ └─┬ nuxt-site-config 3.2.14
β”‚   └── h3 1.15.4 peer
β”œβ”€β”¬ @nuxtjs/sitemap 7.5.1
β”‚ β”œβ”€β”¬ h3-compression 0.3.2
β”‚ β”‚ └── h3 1.15.4 peer
β”‚ └─┬ nuxt-site-config 3.2.14
β”‚   └── h3 1.15.4 peer
β”œβ”€β”¬ nuxt-link-checker 4.3.9
β”‚ β”œβ”€β”¬ nuxt-site-config 3.2.14
β”‚ β”‚ └── h3 1.15.4 peer
β”‚ └─┬ unstorage 1.17.3
β”‚   └── h3 1.15.4
β”œβ”€β”¬ nuxt-og-image 5.1.13
β”‚ β”œβ”€β”¬ nuxt-site-config 3.2.14
β”‚ β”‚ └── h3 1.15.4 peer
β”‚ └─┬ unstorage 1.17.3 peer
β”‚   └── h3 1.15.4
β”œβ”€β”¬ nuxt-schema-org 5.0.10
β”‚ └─┬ nuxt-site-config 3.2.14
β”‚   └── h3 1.15.4 peer
β”œβ”€β”¬ nuxt-seo-utils 7.0.19
β”‚ └─┬ nuxt-site-config 3.2.14
β”‚   └── h3 1.15.4 peer
└─┬ nuxt-site-config 3.2.14
  └── h3 1.15.4 peer
@sentry/nuxt 10.32.1
└─┬ nuxt 4.2.2 peer
  β”œβ”€β”¬ @nuxt/cli 3.32.0
  β”‚ └─┬ listhen 1.9.0
  β”‚   └── h3 1.15.4
  β”œβ”€β”¬ @nuxt/nitro-server 4.2.2
  β”‚ β”œβ”€β”€ h3 1.15.4
  β”‚ β”œβ”€β”¬ nitropack 2.12.9
  β”‚ β”‚ β”œβ”€β”€ h3 1.15.4
  β”‚ β”‚ β”œβ”€β”¬ listhen 1.9.0
  β”‚ β”‚ β”‚ └── h3 1.15.4
  β”‚ β”‚ └─┬ unstorage 1.17.3
  β”‚ β”‚   └── h3 1.15.4
  β”‚ └─┬ unstorage 1.17.3
  β”‚   └── h3 1.15.4
  β”œβ”€β”¬ @nuxt/vite-builder 4.2.2
  β”‚ └── h3 1.15.4
  └── h3 1.15.4
@vueuse/nuxt 14.1.0
└─┬ nuxt 4.2.2 peer
  β”œβ”€β”¬ @nuxt/cli 3.32.0
  β”‚ └─┬ listhen 1.9.0
  β”‚   └── h3 1.15.4
  β”œβ”€β”¬ @nuxt/nitro-server 4.2.2
  β”‚ β”œβ”€β”€ h3 1.15.4
  β”‚ β”œβ”€β”¬ nitropack 2.12.9
  β”‚ β”‚ β”œβ”€β”€ h3 1.15.4
  β”‚ β”‚ β”œβ”€β”¬ listhen 1.9.0
  β”‚ β”‚ β”‚ └── h3 1.15.4
  β”‚ β”‚ └─┬ unstorage 1.17.3
  β”‚ β”‚   └── h3 1.15.4
  β”‚ └─┬ unstorage 1.17.3
  β”‚   └── h3 1.15.4
  β”œβ”€β”¬ @nuxt/vite-builder 4.2.2
  β”‚ └── h3 1.15.4
  └── h3 1.15.4
nuxt 4.2.2
β”œβ”€β”¬ @nuxt/cli 3.32.0
β”‚ └─┬ listhen 1.9.0
β”‚   └── h3 1.15.4
β”œβ”€β”¬ @nuxt/nitro-server 4.2.2
β”‚ β”œβ”€β”€ h3 1.15.4
β”‚ β”œβ”€β”¬ nitropack 2.12.9
β”‚ β”‚ β”œβ”€β”€ h3 1.15.4
β”‚ β”‚ β”œβ”€β”¬ listhen 1.9.0
β”‚ β”‚ β”‚ └── h3 1.15.4
β”‚ β”‚ └─┬ unstorage 1.17.3
β”‚ β”‚   └── h3 1.15.4
β”‚ └─┬ unstorage 1.17.3
β”‚   └── h3 1.15.4
β”œβ”€β”¬ @nuxt/vite-builder 4.2.2
β”‚ └── h3 1.15.4
└── h3 1.15.4
nuxt-auth-utils 0.5.26
└── h3 1.15.4
nuxt-pages-plus 1.0.0-beta.3
└─┬ nuxt 4.2.2 peer
  β”œβ”€β”¬ @nuxt/cli 3.32.0
  β”‚ └─┬ listhen 1.9.0
  β”‚   └── h3 1.15.4
  β”œβ”€β”¬ @nuxt/nitro-server 4.2.2
  β”‚ β”œβ”€β”€ h3 1.15.4
  β”‚ β”œβ”€β”¬ nitropack 2.12.9
  β”‚ β”‚ β”œβ”€β”€ h3 1.15.4
  β”‚ β”‚ β”œβ”€β”¬ listhen 1.9.0
  β”‚ β”‚ β”‚ └── h3 1.15.4
  β”‚ β”‚ └─┬ unstorage 1.17.3
  β”‚ β”‚   └── h3 1.15.4
  β”‚ └─┬ unstorage 1.17.3
  β”‚   └── h3 1.15.4
  β”œβ”€β”¬ @nuxt/vite-builder 4.2.2
  β”‚ └── h3 1.15.4
  └── h3 1.15.4
and with v3.23.0 I get this
❯ pnpm why h3
Legend: production dependency, optional only, dev only

devDependencies:
@nuxt/eslint 1.12.1
└─┬ @eslint/config-inspector 1.4.2
  └── h3 1.15.4
@nuxt/fonts 0.12.1
β”œβ”€β”¬ fontless 0.1.0
β”‚ └─┬ unstorage 1.17.3
β”‚   └── h3 1.15.4
β”œβ”€β”€ h3 1.15.4
└─┬ unstorage 1.17.3
  └── h3 1.15.4
@nuxt/image 2.0.0
β”œβ”€β”€ h3 1.15.4
└─┬ ipx 3.1.1
  β”œβ”€β”€ h3 1.15.4
  β”œβ”€β”¬ listhen 1.9.0
  β”‚ └── h3 1.15.4
  └─┬ unstorage 1.17.3
    └── h3 1.15.4
@nuxt/scripts 0.13.2
β”œβ”€β”€ h3 1.15.4
└─┬ unstorage 1.17.3
  └── h3 1.15.4
@nuxt/test-utils 3.23.0
β”œβ”€β”€ h3 1.15.4
└── h3 2.0.1-rc.7
@nuxt/ui 4.3.0
└─┬ @nuxt/fonts 0.12.1
  β”œβ”€β”¬ fontless 0.1.0
  β”‚ └─┬ unstorage 1.17.3
  β”‚   └── h3 1.15.4
  β”œβ”€β”€ h3 1.15.4
  └─┬ unstorage 1.17.3
    └── h3 1.15.4
@nuxthub/core 0.9.1
β”œβ”€β”€ h3 1.15.4
└─┬ unstorage 1.17.3
  └── h3 1.15.4
@nuxtjs/seo 3.3.0
β”œβ”€β”¬ @nuxtjs/robots 5.6.7
β”‚ └─┬ nuxt-site-config 3.2.14
β”‚   └── h3 2.0.1-rc.7 peer  ⬅️ ⚠️
β”œβ”€β”¬ @nuxtjs/sitemap 7.5.1
β”‚ β”œβ”€β”¬ h3-compression 0.3.2 
β”‚ β”‚ └── h3 2.0.1-rc.7 peer ⬅️ ⚠️
β”‚ └─┬ nuxt-site-config 3.2.14
β”‚   └── h3 2.0.1-rc.7 peer ⬅️ ⚠️
β”œβ”€β”¬ nuxt-link-checker 4.3.9
β”‚ β”œβ”€β”¬ nuxt-site-config 3.2.14
β”‚ β”‚ └── h3 2.0.1-rc.7 peer ⬅️ ⚠️
β”‚ └─┬ unstorage 1.17.3
β”‚   └── h3 1.15.4
β”œβ”€β”¬ nuxt-og-image 5.1.13
β”‚ β”œβ”€β”¬ nuxt-site-config 3.2.14
β”‚ β”‚ └── h3 2.0.1-rc.7 peer ⬅️ ⚠️
β”‚ └─┬ unstorage 1.17.3 peer
β”‚   └── h3 1.15.4
β”œβ”€β”¬ nuxt-schema-org 5.0.10
β”‚ └─┬ nuxt-site-config 3.2.14
β”‚   └── h3 2.0.1-rc.7 peer
β”œβ”€β”¬ nuxt-seo-utils 7.0.19
β”‚ └─┬ nuxt-site-config 3.2.14
β”‚   └── h3 2.0.1-rc.7 peer
└─┬ nuxt-site-config 3.2.14
  └── h3 2.0.1-rc.7 peer
@sentry/nuxt 10.32.1
└─┬ nuxt 4.2.2 peer
  β”œβ”€β”¬ @nuxt/cli 3.32.0
  β”‚ └─┬ listhen 1.9.0
  β”‚   └── h3 1.15.4
  β”œβ”€β”¬ @nuxt/nitro-server 4.2.2
  β”‚ β”œβ”€β”€ h3 1.15.4
  β”‚ β”œβ”€β”¬ nitropack 2.12.9
  β”‚ β”‚ β”œβ”€β”€ h3 1.15.4
  β”‚ β”‚ β”œβ”€β”¬ listhen 1.9.0
  β”‚ β”‚ β”‚ └── h3 1.15.4
  β”‚ β”‚ └─┬ unstorage 1.17.3
  β”‚ β”‚   └── h3 1.15.4
  β”‚ └─┬ unstorage 1.17.3
  β”‚   └── h3 1.15.4
  β”œβ”€β”¬ @nuxt/vite-builder 4.2.2
  β”‚ └── h3 1.15.4
  └── h3 1.15.4
@vueuse/nuxt 14.1.0
└─┬ nuxt 4.2.2 peer
  β”œβ”€β”¬ @nuxt/cli 3.32.0
  β”‚ └─┬ listhen 1.9.0
  β”‚   └── h3 1.15.4
  β”œβ”€β”¬ @nuxt/nitro-server 4.2.2
  β”‚ β”œβ”€β”€ h3 1.15.4
  β”‚ β”œβ”€β”¬ nitropack 2.12.9
  β”‚ β”‚ β”œβ”€β”€ h3 1.15.4
  β”‚ β”‚ β”œβ”€β”¬ listhen 1.9.0
  β”‚ β”‚ β”‚ └── h3 1.15.4
  β”‚ β”‚ └─┬ unstorage 1.17.3
  β”‚ β”‚   └── h3 1.15.4
  β”‚ └─┬ unstorage 1.17.3
  β”‚   └── h3 1.15.4
  β”œβ”€β”¬ @nuxt/vite-builder 4.2.2
  β”‚ └── h3 1.15.4
  └── h3 1.15.4
nuxt 4.2.2
β”œβ”€β”¬ @nuxt/cli 3.32.0
β”‚ └─┬ listhen 1.9.0
β”‚   └── h3 1.15.4
β”œβ”€β”¬ @nuxt/nitro-server 4.2.2
β”‚ β”œβ”€β”€ h3 1.15.4
β”‚ β”œβ”€β”¬ nitropack 2.12.9
β”‚ β”‚ β”œβ”€β”€ h3 1.15.4
β”‚ β”‚ β”œβ”€β”¬ listhen 1.9.0
β”‚ β”‚ β”‚ └── h3 1.15.4
β”‚ β”‚ └─┬ unstorage 1.17.3
β”‚ β”‚   └── h3 1.15.4
β”‚ └─┬ unstorage 1.17.3
β”‚   └── h3 1.15.4
β”œβ”€β”¬ @nuxt/vite-builder 4.2.2
β”‚ └── h3 1.15.4
└── h3 1.15.4
nuxt-auth-utils 0.5.26
└── h3 1.15.4
nuxt-pages-plus 1.0.0-beta.3
└─┬ nuxt 4.2.2 peer
  β”œβ”€β”¬ @nuxt/cli 3.32.0
  β”‚ └─┬ listhen 1.9.0
  β”‚   └── h3 1.15.4
  β”œβ”€β”¬ @nuxt/nitro-server 4.2.2
  β”‚ β”œβ”€β”€ h3 1.15.4
  β”‚ β”œβ”€β”¬ nitropack 2.12.9
  β”‚ β”‚ β”œβ”€β”€ h3 1.15.4
  β”‚ β”‚ β”œβ”€β”¬ listhen 1.9.0
  β”‚ β”‚ β”‚ └── h3 1.15.4
  β”‚ β”‚ └─┬ unstorage 1.17.3
  β”‚ β”‚   └── h3 1.15.4
  β”‚ └─┬ unstorage 1.17.3
  β”‚   └── h3 1.15.4
  β”œβ”€β”¬ @nuxt/vite-builder 4.2.2
  β”‚ └── h3 1.15.4
  └── h3 1.15.4

@Yizack
Copy link
Contributor

Yizack commented Jan 7, 2026

Would this possibly cause issue with pnpm when using another module like nuxt-site-config which has "h3": ">=1" as peerDependencies?

Same issue here πŸ‘‹ Can't run nuxt dev

Logs
β„Ή Vite server warmed up in 1ms                                                                                                                                                  9:58:02 p. m.
β„Ή Vite client warmed up in 7ms   
[h3] Implicit event handler conversion is deprecated. Use eventHandler() or fromNodeMiddleware() to define event handlers.                                                       9:58:04 p. m.
     Handler: async (e) => {
  if (e.context._initedSiteConfig)
    return;
  const runtimeConfig = useRuntimeConfig(e);
  const config = runtimeConfig["nuxt-site-config"];
  const nitroApp = useNitroApp();
  const siteConfig = e.context.siteConfig || createSiteConfigStack({
    debug: config.debug
  });
  const nitroOrigin = getNitroOrigin(e);
  e.context.siteConfigNitroOrigin = nitroOrigin;
  {
    siteConfig.push({
      _context: "nitro:init",
      _priority: -4,
      url: nitroOrigin
    });
  }
  siteConfig.push({
    _context: "runtimeEnv",
    _priority: 0,
    ...runtimeConfig.site || {},
    ...runtimeConfig.public.site || {},
    ...envSiteConfig(globalThis._importMeta_.env)
    // just in-case, shouldn't be needed
  });
  const buildStack = config.stack || [];
  buildStack.forEach((c) => siteConfig.push(c));
  if (e.context._nitro.routeRules.site) {
    siteConfig.push({
      _context: "route-rules",
      ...e.context._nitro.routeRules.site
    });
  }
  if (config.multiTenancy) {
    const host = parseURL(nitroOrigin).host;
    const tenant = config.multiTenancy?.find((t) => t.hosts.includes(host));
    if (tenant) {
      siteConfig.push({
        _context: multi-tenancy:${host},
        _priority: 0,
        ...tenant.config
      });
    }
  }
  const ctx = { siteConfig, event: e };
  await nitroApp.hooks.callHook("site-config:init", ctx);
  e.context.siteConfig = ctx.siteConfig;
  e.context._initedSiteConfig = true;
}
[h3] Implicit event handler conversion is deprecated. Use eventHandler() or fromNodeMiddleware() to define event handlers.                                                       9:58:04 p. m.  
     Route: /__site-config__/debug.json
     Handler: async (e) => {
  const siteConfig = getSiteConfig(e);
  const nitroOrigin = getNitroOrigin(e);
  const runtimeConfig = useRuntimeConfig(e);
  const stack = e.context.siteConfig.stack;
  setHeader(e, "Content-Type", "application/json");
  return {
    config: siteConfig,
    stack,
    nitroOrigin,
    version: runtimeConfig["nuxt-site-config"].version
  };
}

@harlan-zw
Copy link
Contributor

Hm yeh let me fix this in nuxt-site-config

@cadenzah
Copy link

cadenzah commented Jan 7, 2026

I got similar issue, after I updated to v3.23.0, and run nuxt dev, the build runs okay but it shows an error like below and fails:

β„Ή Error: event.req.headers.entries is not a function or its return value is not iterable

 ⁃ at getProxyRequestHeaders (node_modules/.pnpm/[email protected]/node_modules/h3/dist/h3.mjs:1292:48)

   1287 ┃       });
   1288 ┃  }
   1289 ┃  
   1290 ┃  function getProxyRequestHeaders(event, opts) {
   1291 ┃       const headers = new EmptyObject();
 ❯ 1292 ┃       for (const [name, value] of event.req.headers.entries()) {
   1293 ┃               if (opts?.filterHeaders?.includes(name)) continue;
   1294 ┃               if (opts?.forwardHeaders?.includes(name)) {
   1295 ┃                       headers[name] = value;
   1296 ┃                       continue;
   1297 ┃               }

 ⁃ at proxyRequest (node_modules/.pnpm/[email protected]/node_modules/h3/dist/h3.mjs:1233:36)
 ⁃ at Object.handler (node_modules/.pnpm/[email protected][email protected]/node_modules/h3-proxy/lib/index.esm.js:445:20)
 ⁃ at process.processTicksAndRejections (node:internal/process/task_queues:103:5)
 ⁃ (async file://node_modules/.pnpm/[email protected]/node_modules/h3/dist/index.mjs:2004:19)
 ⁃ at async Object.callAsync (node_modules/.pnpm/[email protected]/node_modules/unctx/dist/index.mjs:72:16)
 ⁃ at async Server.toNodeHandle (node_modules/.pnpm/[email protected]/node_modules/h3/dist/index.mjs:2296:7)

@harlan-zw
Copy link
Contributor

If you're using any of the Nuxt SEO modules make sure you clear your lock file + node_modules and re-install, it should fix it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants